home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / c / TinyGL.lha / tinygl / src / glx.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-01  |  10.4 KB  |  414 lines

  1. /* simple glx driver for TinyGL */
  2. #include <GL/glx.h>
  3. #include <sys/ipc.h>
  4. #include <sys/shm.h>
  5. #include <X11/extensions/XShm.h>
  6. #include "zgl.h"
  7.  
  8. typedef struct {
  9.   GLContext *gl_context;
  10.   Display *display;
  11.   XVisualInfo visual_info;
  12.   int xsize,ysize;
  13.   XImage *ximage;
  14.   GC gc;
  15.   Colormap cmap;
  16.   Drawable drawable;
  17.   int do_convert; /* true if must do convertion to X11 format */
  18.   /* shared memory */
  19.   int shm_use;
  20.   XShmSegmentInfo *shm_info;
  21.   int CompletionType;
  22. } TinyGLXContext;
  23.  
  24. Bool glXQueryExtension( Display *dpy, int *errorb, int *event )
  25. {
  26.     return True;
  27. }
  28.  
  29.  
  30. XVisualInfo* glXChooseVisual( Display *dpy, int screen,
  31.                               int *attribList )
  32. {
  33.     XVisualInfo vinfo;
  34.     int n;
  35.     
  36.     /* the attribList is ignored : we consider only RGBA rendering (no
  37.        direct color) */
  38.     
  39.     if (XMatchVisualInfo (dpy, screen, 16, TrueColor, &vinfo)) {
  40.         /* 16 bit visual (fastest with TinyGL) */
  41.     } else if (XMatchVisualInfo (dpy, screen, 24, TrueColor, &vinfo)) {
  42.         /* 24 bit visual */
  43.     } else if (XMatchVisualInfo (dpy, screen, 32, TrueColor, &vinfo)) {
  44.         /* 32 bit visual */
  45.     } else if (XMatchVisualInfo (dpy, screen, 8, PseudoColor, &vinfo)) {
  46.         /* 8 bit visual */
  47.     } else {
  48.         /* no suitable visual */
  49.         return NULL;
  50.     }
  51.     
  52.     return XGetVisualInfo(dpy,VisualAllMask,&vinfo,&n);
  53. }
  54.  
  55.  
  56.  
  57. GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis,
  58.                              GLXContext shareList, Bool direct )
  59. {
  60.   TinyGLXContext *ctx;
  61.  
  62.   if (shareList != NULL) {
  63.     gl_fatal_error("No sharing available in TinyGL");
  64.   }
  65.   ctx=gl_malloc(sizeof(TinyGLXContext));
  66.   ctx->gl_context=NULL;
  67.   ctx->visual_info=*vis;
  68.   return (GLXContext) ctx;
  69. }
  70.  
  71.  
  72. void glXDestroyContext( Display *dpy, GLXContext ctx1 )
  73. {
  74.   TinyGLXContext *ctx = (TinyGLXContext *) ctx1;
  75.   if (ctx->gl_context != NULL) {
  76.     glClose();
  77.   }
  78.   gl_free(ctx);
  79. }
  80.  
  81.  
  82. static int glxXErrorFlag=0;
  83.  
  84. static int glxHandleXError(Display *dpy,XErrorEvent *event)
  85. {
  86.   glxXErrorFlag=1;
  87.   return 0;
  88. }
  89.  
  90. static int bits_per_pixel(Display *dpy, XVisualInfo *visinfo)
  91. {
  92.    XImage *img;
  93.    int bpp;
  94.    char *data;
  95.  
  96.    data = gl_malloc(8);
  97.    if (data == NULL) 
  98.        return visinfo->depth;
  99.  
  100.    img = XCreateImage(dpy, visinfo->visual, visinfo->depth,
  101.                       ZPixmap, 0, data, 1, 1, 32, 0);
  102.    if (img == NULL) {
  103.        gl_free(data);
  104.        return visinfo->depth;
  105.    }
  106.    bpp = img->bits_per_pixel;
  107.    gl_free(data);
  108.    img->data = NULL;
  109.    XDestroyImage(img);
  110.    return bpp;
  111. }
  112.  
  113. static int create_ximage(TinyGLXContext *ctx,
  114.                          int xsize,int ysize,int depth)
  115. {
  116.   int major,minor;
  117.   Bool pixmaps;
  118.   unsigned char *framebuffer;
  119.   int (*old_handler)(Display *,XErrorEvent *);
  120.  
  121.   if (XShmQueryVersion(ctx->display,&major,&minor,&pixmaps))
  122.     ctx->shm_use=1;
  123.   else
  124.     ctx->shm_use=0;
  125.  
  126.   if (!ctx->shm_use) goto no_shm;
  127.  
  128.   ctx->shm_info=gl_malloc(sizeof(XShmSegmentInfo));
  129.   ctx->ximage=XShmCreateImage(ctx->display,None,depth,ZPixmap,NULL,
  130.                               ctx->shm_info,xsize,ysize);
  131.   if (ctx->ximage == NULL) {
  132.     fprintf(stderr,"XShm: error: XShmCreateImage\n");
  133.     ctx->shm_use=0;
  134.     gl_free(ctx->shm_info);
  135.     goto no_shm;
  136.   }
  137.   ctx->shm_info->shmid=shmget(IPC_PRIVATE,
  138.                               ctx->ysize*ctx->ximage->bytes_per_line,
  139.                               IPC_CREAT | 0777);
  140.   if (ctx->shm_info->shmid < 0) {
  141.     fprintf(stderr,"XShm: error: shmget\n");
  142.   no_shm1:
  143.     ctx->shm_use=0;
  144.     XDestroyImage(ctx->ximage);
  145.     goto no_shm;
  146.   }
  147.   ctx->ximage->data=shmat(ctx->shm_info->shmid,0,0);
  148.   if (ctx->ximage->data == (char *) -1) {
  149.     fprintf(stderr,"XShm: error: shmat\n");
  150.   no_shm2:
  151.     shmctl(ctx->shm_info->shmid,IPC_RMID,0);
  152.     goto no_shm1;
  153.   }
  154.   ctx->shm_info->shmaddr=ctx->ximage->data;
  155.   
  156.   ctx->shm_info->readOnly=False;
  157.  
  158.   /* attach & test X errors */
  159.  
  160.   glxXErrorFlag=0;
  161.   old_handler=XSetErrorHandler(glxHandleXError);
  162.   XShmAttach(ctx->display,ctx->shm_info);
  163.   XSync(ctx->display, False);
  164.   
  165.   if (glxXErrorFlag) {
  166.     XFlush(ctx->display);
  167.     shmdt(ctx->shm_info->shmaddr);
  168.     XSetErrorHandler(old_handler);
  169.     goto no_shm2;
  170.   }
  171.  
  172.   /* the shared memory will be automatically deleted */
  173.   shmctl(ctx->shm_info->shmid,IPC_RMID,0);
  174.  
  175.   /* test with a dummy XShmPutImage */
  176.   XShmPutImage(ctx->display,ctx->drawable,ctx->gc,
  177.                ctx->ximage,0,0,0,0,1,1,
  178.                False);
  179.  
  180.   XSync(ctx->display, False);
  181.   XSetErrorHandler(old_handler);
  182.   
  183.   if (glxXErrorFlag) {
  184.     fprintf(stderr,"XShm: error: XShmPutImage\n");
  185.     XFlush(ctx->display);
  186.     shmdt(ctx->shm_info->shmaddr);
  187.     goto no_shm2;
  188.   }
  189.   
  190.   ctx->CompletionType=XShmGetEventBase(ctx->display) + ShmCompletion;
  191.   /* shared memory is OK !! */
  192.  
  193.   return 0;
  194.  
  195.   no_shm:
  196.     ctx->ximage=XCreateImage(ctx->display, None, depth, ZPixmap, 0, 
  197.                              NULL,xsize,ysize, 8, 0);
  198.     framebuffer=gl_malloc(ysize * ctx->ximage->bytes_per_line);
  199.     ctx->ximage->data = framebuffer;
  200.     return 0;
  201. }
  202.  
  203. static void free_ximage(TinyGLXContext *ctx)
  204. {
  205.   if (ctx->shm_use)
  206.   {
  207.     XShmDetach(ctx->display, ctx->shm_info);
  208.     XDestroyImage(ctx->ximage);
  209.     shmdt(ctx->shm_info->shmaddr);
  210.     gl_free(ctx->shm_info);
  211.   } else {
  212.     gl_free(ctx->ximage->data);
  213.     XDestroyImage(ctx->ximage);
  214.   }
  215. }
  216.  
  217. /* resize the glx viewport : we try to use the xsize and ysize
  218.    given. We return the effective size which is guaranted to be smaller */
  219.  
  220. int glX_resize_viewport(GLContext *c,int *xsize_ptr,int *ysize_ptr)
  221. {
  222.   TinyGLXContext *ctx;
  223.   int xsize,ysize;
  224.  
  225.   ctx=(TinyGLXContext *)c->opaque;
  226.  
  227.   xsize=*xsize_ptr;
  228.   ysize=*ysize_ptr;
  229.  
  230.   /* we ensure that xsize and ysize are multiples of 2 for the zbuffer. 
  231.      TODO: find a better solution */
  232.   xsize&=~3;
  233.   ysize&=~3;
  234.  
  235.   if (xsize == 0 || ysize == 0) return -1;
  236.  
  237.   *xsize_ptr=xsize;
  238.   *ysize_ptr=ysize;
  239.  
  240.   if (ctx->ximage != NULL) free_ximage(ctx);
  241.   
  242.   ctx->xsize=xsize;
  243.   ctx->ysize=ysize;
  244.  
  245.   if (create_ximage(ctx,ctx->xsize,ctx->ysize,ctx->visual_info.depth) != 0) 
  246.     return -1;
  247.  
  248.   /* resize the Z buffer */
  249.   if (ctx->do_convert) {
  250.     ZB_resize(c->zb,NULL,xsize,ysize);
  251.   } else {
  252.     ZB_resize(c->zb,ctx->ximage->data,xsize,ysize);
  253.   }
  254.   return 0;
  255. }
  256.  
  257. /* we assume here that drawable is a window */
  258. Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable,
  259.                      GLXContext ctx1)
  260. {
  261.   TinyGLXContext *ctx = (TinyGLXContext *) ctx1;
  262.   XWindowAttributes attr;
  263.   int i,xsize,ysize;
  264.   unsigned int palette[ZB_NB_COLORS];
  265.   unsigned char color_indexes[ZB_NB_COLORS];
  266.   ZBuffer *zb;
  267.   XColor xcolor;
  268.   unsigned long pixel[ZB_NB_COLORS],tmp_plane;
  269.   
  270.   if (ctx->gl_context == NULL) {
  271.     /* create the TinyGL context */
  272.  
  273.     ctx->display=dpy;
  274.     ctx->drawable=drawable;
  275.  
  276.     XGetWindowAttributes(ctx->display,drawable,&attr);
  277.  
  278.     xsize=attr.width;
  279.     ysize=attr.height;
  280.  
  281.     if (attr.depth != ctx->visual_info.depth) return False;
  282.  
  283.     /* ximage structure */
  284.     ctx->ximage=NULL;
  285.     ctx->shm_use=1; /* use shm */
  286.  
  287.     if (attr.depth == 8) {
  288.       /* get the colormap from the window */
  289.       ctx->cmap = attr.colormap;
  290.  
  291.       if ( XAllocColorCells(ctx->display,ctx->cmap,True,&tmp_plane,0,
  292.                             pixel,ZB_NB_COLORS) == 0) {
  293.         /* private cmap */
  294.         ctx->cmap = XCreateColormap(ctx->display, drawable,  
  295.                                     ctx->visual_info.visual, AllocAll);
  296.         XSetWindowColormap(ctx->display, drawable, ctx->cmap);
  297.         for(i=0;i<ZB_NB_COLORS;i++) pixel[i]=i;
  298.       }
  299.  
  300.       for(i=0;i<ZB_NB_COLORS;i++) color_indexes[i]=pixel[i];
  301.  
  302.       /* Open the Z Buffer - 256 colors */
  303.       zb=ZB_open(xsize,ysize,ZB_MODE_INDEX,ZB_NB_COLORS,
  304.                  color_indexes,palette,NULL);
  305.       if (zb == NULL) {
  306.         fprintf(stderr, "Error while initializing Z buffer\n");
  307.         exit(1);
  308.       }
  309.  
  310.       for (i=0; i<ZB_NB_COLORS; i++) {
  311.         xcolor.flags = DoRed | DoGreen | DoBlue;
  312.         
  313.         xcolor.red = (palette[i]>>8) & 0xFF00;
  314.         xcolor.green = (palette[i] & 0xFF00);
  315.         xcolor.blue = (palette[i] << 8) & 0xFF00;
  316.         xcolor.pixel = pixel[i];
  317.         XStoreColor(ctx->display,ctx->cmap,&xcolor);
  318.       }
  319.       ctx->do_convert = 1;
  320.     } else {
  321.         int mode,bpp;
  322.         /* RGB 16/24/32 */
  323.         bpp = bits_per_pixel(ctx->display,&ctx->visual_info);
  324.         switch(bpp) {
  325.         case 24:
  326.             mode = ZB_MODE_RGB24;
  327.             ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 16);
  328.             break;
  329.         case 32:
  330.             mode = ZB_MODE_RGBA;
  331.             ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 16);
  332.             break;
  333.         default:
  334.             mode = ZB_MODE_5R6G5B;
  335.             ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 16);
  336.             break;
  337.         }
  338.         zb=ZB_open(xsize,ysize,mode,0,NULL,NULL,NULL);
  339.         if (zb == NULL) {
  340.             fprintf(stderr, "Error while initializing Z buffer\n");
  341.             exit(1);
  342.         }
  343.     }
  344.  
  345.     /* create a gc */
  346.     ctx->gc = XCreateGC(ctx->display, drawable, 0, 0);
  347.  
  348.     /* initialisation of the TinyGL interpreter */
  349.     glInit(zb);
  350.     ctx->gl_context=gl_get_context();
  351.     ctx->gl_context->opaque=(void *) ctx;
  352.     ctx->gl_context->gl_resize_viewport=glX_resize_viewport;
  353.  
  354.     /* set the viewport : we force a call to glX_resize_viewport */
  355.     ctx->gl_context->viewport.xsize=-1;
  356.     ctx->gl_context->viewport.ysize=-1;
  357.  
  358.     glViewport(0, 0, xsize, ysize);
  359.   }
  360.  
  361.   return True;
  362. }
  363.  
  364. static Bool WaitForShmCompletion(Display *dpy, XEvent *event, char *arg) 
  365. {
  366.     TinyGLXContext *ctx=(TinyGLXContext *) arg;
  367.  
  368.     return (event->type == ctx->CompletionType) && 
  369.         ( ((XShmCompletionEvent *)event)->drawable == (Window)ctx->drawable); 
  370. }
  371.  
  372. void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
  373. {
  374.   GLContext *gl_context;
  375.   TinyGLXContext *ctx;
  376.  
  377.   /* retrieve the current GLXContext */
  378.   gl_context=gl_get_context();
  379.   ctx=(TinyGLXContext *)gl_context->opaque;
  380.  
  381.   /* for non 16 bits visuals, a conversion is required */
  382.   
  383.  
  384.   if (ctx->do_convert) {
  385.     ZB_copyFrameBuffer(ctx->gl_context->zb,
  386.                        ctx->ximage->data,
  387.                        ctx->ximage->bytes_per_line);
  388.  
  389.   }
  390.  
  391.   /* draw the ximage */
  392.   if (ctx->shm_use) {
  393.       XEvent event;
  394.  
  395.       XShmPutImage(dpy,drawable,ctx->gc,
  396.                    ctx->ximage,0,0,0,0,ctx->ximage->width, ctx->ximage->height,
  397.                    True);
  398.       XIfEvent(dpy, &event, WaitForShmCompletion, (char*)ctx);
  399.   } else {
  400.     XPutImage(dpy, drawable, ctx->gc, 
  401.               ctx->ximage, 0, 0, 0, 0, ctx->ximage->width, ctx->ximage->height);
  402.   }
  403.   XFlush(dpy);
  404. }
  405.  
  406.  
  407. void glXWaitGL( void )
  408. {
  409. }
  410.  
  411. void glXWaitX( void )
  412. {
  413. }
  414.